﻿using Microsoft.AspNetCore.Mvc;
using SD.Infrastructure.DTOBase;
using SD.Toolkits.AspNetCore.Attributes;
using SlamDunk.MES.IAppService.DTOs.Inputs;
using SlamDunk.MES.IAppService.DTOs.Outputs.StockContext;
using SlamDunk.MES.IAppService.Interfaces;
using SlamDunk.MES.ReportView.Models;
using SlamDunk.ValueObjects.Enums;
using System;
using System.Collections.Generic;

namespace SlamDunk.MES.AppService.Host.Controllers
{
    /// <summary>
    /// 库存管理服务WebApi接口
    /// </summary>
    [ApiController]
    [Route("Api/[controller]/[action]")]
    public class StockManageController : ControllerBase
    {
        #region # 字段及构造器

        /// <summary>
        /// 库存管理服务契约接口
        /// </summary>
        private readonly IStockManageContract _stockManageContract;

        /// <summary>
        /// 依赖注入构造器
        /// </summary>
        public StockManageController(IStockManageContract stockManageContract)
        {
            this._stockManageContract = stockManageContract;
        }

        #endregion


        //命令部分

        #region # 创建物料批次 —— void CreateMaterialLot(Guid materialId, Guid supplierId...
        /// <summary>
        /// 创建物料批次
        /// </summary>
        /// <param name="materialId">物料定义Id</param>
        /// <param name="supplierId">供应商Id</param>
        /// <param name="productionBatchNo">生产批号</param>
        /// <param name="producedDate">生产日期</param>
        /// <param name="guaranteePeriod">保质期</param>
        /// <param name="expiredDate">过期日期</param>
        /// <param name="receptionDate">接收日期</param>
        /// <param name="specification">规格</param>
        /// <param name="initialQuantity">初始数量</param>
        /// <param name="materialSourceType">物料来源</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="description">描述</param>
        [HttpPost]
        [WrapPostParameters]
        public void CreateMaterialLot(Guid materialId, Guid supplierId, string productionBatchNo, DateTime producedDate, TimeSpan guaranteePeriod, DateTime expiredDate, DateTime receptionDate, string specification, decimal? initialQuantity, MaterialSourceType materialSourceType, Guid? facilityId, string description)
        {
            this._stockManageContract.CreateMaterialLot(materialId, supplierId, productionBatchNo, producedDate, guaranteePeriod, expiredDate, receptionDate, specification, initialQuantity, materialSourceType, facilityId, description);
        }
        #endregion

        #region # 修改物料批次 —— void UpdateMaterialLot(Guid materialLotId, Guid supplierId...
        /// <summary>
        /// 修改物料批次
        /// </summary>
        /// <param name="materialLotId">物料批次Id</param>
        /// <param name="supplierId">供应商Id</param>
        /// <param name="productionBatchNo">生产批号</param>
        /// <param name="producedDate">生产日期</param>
        /// <param name="guaranteePeriod">保质期</param>
        /// <param name="expiredDate">过期日期</param>
        /// <param name="receptionDate">接收日期</param>
        /// <param name="specification">规格</param>
        /// <param name="initialQuantity">初始数量</param>
        /// <param name="materialSourceType">物料来源</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="description">描述</param>
        [HttpPost]
        [WrapPostParameters]
        public void UpdateMaterialLot(Guid materialLotId, Guid supplierId, string productionBatchNo, DateTime producedDate, TimeSpan guaranteePeriod, DateTime expiredDate, DateTime receptionDate, string specification, decimal? initialQuantity, MaterialSourceType materialSourceType, Guid? facilityId, string description)
        {
            this._stockManageContract.UpdateMaterialLot(materialLotId, supplierId, productionBatchNo, producedDate, guaranteePeriod, expiredDate, receptionDate, specification, initialQuantity, materialSourceType, facilityId, description);
        }
        #endregion

        #region # 生成物料条码 —— string GenerateMaterialBacode(Guid materialId...
        /// <summary>
        /// 生成物料条码
        /// </summary>
        /// <param name="materialId">物料定义Id</param>
        /// <param name="materialLotId">物料批次Id</param>
        /// <returns>物料条码编号</returns>
        [HttpPost]
        [WrapPostParameters]
        public string GenerateMaterialBacode(Guid materialId, Guid? materialLotId)
        {
            return this._stockManageContract.GenerateMaterialBacode(materialId, materialLotId);
        }
        #endregion

        #region # 批量生成物料条码 —— IEnumerable<string> GenerateMaterialBacodes(Guid...
        /// <summary>
        /// 批量生成物料条码
        /// </summary>
        /// <param name="materialId">物料定义Id</param>
        /// <param name="materialLotId">物料批次Id</param>
        /// <param name="count">条码数量</param>
        /// <returns>物料条码编号列表</returns>
        [HttpPost]
        [WrapPostParameters]
        public IEnumerable<string> GenerateMaterialBacodes(Guid materialId, Guid? materialLotId, int count)
        {
            return this._stockManageContract.GenerateMaterialBacodes(materialId, materialLotId, count);
        }
        #endregion

        #region # 结转库存 —— void SettleStock(Guid materialId, Guid? materialLotId...
        /// <summary>
        /// 结转库存
        /// </summary>
        /// <param name="materialId">物料定义Id</param>
        /// <param name="materialLotId">物料批次Id</param>
        /// <param name="materialLotParam">物料批次参数模型</param>
        /// <param name="storageLocationType">储存位置类型</param>
        /// <param name="storageLocationId">储存位置Id</param>
        /// <param name="storageLocationName">储存位置名称</param>
        /// <param name="settledDate">结转日期</param>
        /// <param name="quantity">数量</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="description">描述</param>
        [HttpPost]
        [WrapPostParameters]
        public void SettleStock(Guid materialId, Guid? materialLotId, MaterialLotParam? materialLotParam, StorageLocationType storageLocationType, string storageLocationId, string storageLocationName, DateTime settledDate, decimal quantity, Guid? facilityId, string description)
        {
            this._stockManageContract.SettleStock(materialId, materialLotId, materialLotParam, storageLocationType, storageLocationId, storageLocationName, settledDate, quantity, facilityId, description);
        }
        #endregion


        //查询部分

        #region # 分页获取物料批次列表 —— PageModel<MaterialLotInfo> GetMaterialLotsByPage(string keywords...
        /// <summary>
        /// 分页获取物料批次列表
        /// </summary>
        /// <param name="keywords">关键字</param>
        /// <param name="materialId">物料定义Id</param>
        /// <param name="supplierId">供应商Id</param>
        /// <param name="startProducedDate">生产日期开始</param>
        /// <param name="endProducedDate">生产日期结束</param>
        /// <param name="startExpiredDate">过期日期开始</param>
        /// <param name="endExpiredDate">过期日期结束</param>
        /// <param name="startReceptionDate">接收日期开始</param>
        /// <param name="endReceptionDate">接收日期结束</param>
        /// <param name="materialSourceType">物料来源类型</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页容量</param>
        /// <returns>物料批次列表</returns>
        [HttpGet]
        public PageModel<MaterialLotInfo> GetMaterialLotsByPage(string keywords, Guid? materialId, Guid? supplierId, DateTime? startProducedDate, DateTime? endProducedDate, DateTime? startExpiredDate, DateTime? endExpiredDate, DateTime? startReceptionDate, DateTime? endReceptionDate, MaterialSourceType? materialSourceType, Guid? facilityId, int pageIndex, int pageSize)
        {
            return this._stockManageContract.GetMaterialLotsByPage(keywords, materialId, supplierId, startProducedDate, endProducedDate, startExpiredDate, endExpiredDate, startReceptionDate, endReceptionDate, materialSourceType, facilityId, pageIndex, pageSize);
        }
        #endregion

        #region # 分页获取物料条码列表 —— PageModel<MaterialBarcodeInfo> GetMaterialBarcodesByPage(Guid?...
        /// <summary>
        /// 分页获取物料条码列表
        /// </summary>
        /// <param name="materialId">物料定义Id</param>
        /// <param name="materialLotId">物料批次Id</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页容量</param>
        /// <returns>物料条码列表</returns>
        [HttpGet]
        public PageModel<MaterialBarcodeInfo> GetMaterialBarcodesByPage(Guid? materialId, Guid? materialLotId, Guid? facilityId, int pageIndex, int pageSize)
        {
            return this._stockManageContract.GetMaterialBarcodesByPage(materialId, materialLotId, facilityId, pageIndex, pageSize);
        }
        #endregion

        #region # 根据编号获取物料条码字典 —— IDictionary<string, MaterialBarcodeInfo> GetMaterialBarcodesByNo(...
        /// <summary>
        /// 根据编号获取物料条码字典
        /// </summary>
        /// <param name="materialBarcodeNos">物料条码编号集</param>
        /// <returns>物料条码字典</returns>
        [HttpGet]
        public IDictionary<string, MaterialBarcodeInfo> GetMaterialBarcodesByNo(IEnumerable<string> materialBarcodeNos)
        {
            return this._stockManageContract.GetMaterialBarcodesByNo(materialBarcodeNos);
        }
        #endregion

        #region # 分页获取库存结转记录列表 —— PageModel<StockSettlementInfo> GetStockSettlementsByPage(...
        /// <summary>
        /// 分页获取库存结转记录列表
        /// </summary>
        /// <param name="materialId">物料定义Id</param>
        /// <param name="materialLotId">物料批次Id</param>
        /// <param name="storageLocationType">储存位置类型</param>
        /// <param name="storageLocationId">储存位置Id</param>
        /// <param name="startSettledDate">结转日期开始</param>
        /// <param name="endSettledDate">结转日期结束</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页容量</param>
        /// <returns>库存结转记录列表</returns>
        [HttpGet]
        public PageModel<StockSettlementInfo> GetStockSettlementsByPage(Guid? materialId, Guid? materialLotId, StorageLocationType? storageLocationType, string storageLocationId, DateTime? startSettledDate, DateTime? endSettledDate, Guid? facilityId, int pageIndex, int pageSize)
        {
            return this._stockManageContract.GetStockSettlementsByPage(materialId, materialLotId, storageLocationType, storageLocationId, startSettledDate, endSettledDate, facilityId, pageIndex, pageSize);
        }
        #endregion

        #region # 分页获取物料库存列表 —— PageModel<MaterialStockInfo> GetMaterialStocksByPage(string keywords...
        /// <summary>
        /// 分页获取物料库存列表
        /// </summary>
        /// <param name="keywords">关键字</param>
        /// <param name="materialId">物料定义Id</param>
        /// <param name="materialLotId">物料批次Id</param>
        /// <param name="supplierId">供应商Id</param>
        /// <param name="storageLocationType">储存位置类型</param>
        /// <param name="storageLocationId">储存位置Id</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页容量</param>
        /// <returns>物料库存列表</returns>
        [HttpGet]
        public PageModel<MaterialStockInfo> GetMaterialStocksByPage(string keywords, Guid? materialId, Guid? materialLotId, Guid? supplierId, StorageLocationType? storageLocationType, string storageLocationId, Guid? facilityId, int pageIndex, int pageSize)
        {
            return this._stockManageContract.GetMaterialStocksByPage(keywords, materialId, materialLotId, supplierId, storageLocationType, storageLocationId, facilityId, pageIndex, pageSize);
        }
        #endregion

        #region # 分页获取出/入库记录列表 —— PageModel<BoundRecordInfo> GetBoundRecordsByPage(Guid? materialId...
        /// <summary>
        /// 分页获取出/入库记录列表
        /// </summary>
        /// <param name="materialId">物料定义Id</param>
        /// <param name="materialLotId">物料批次Id</param>
        /// <param name="directionType">出/入库方向类型</param>
        /// <param name="storageLocationType">储存位置类型</param>
        /// <param name="storageLocationId">储存位置Id</param>
        /// <param name="stockOrderClassId">库存单据类Id</param>
        /// <param name="stockOrderId">库存单据Id</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页容量</param>
        /// <returns>出/入库记录列表</returns>
        [HttpGet]
        public PageModel<BoundRecordInfo> GetBoundRecordsByPage(Guid? materialId, Guid? materialLotId, StockDirectionType? directionType, StorageLocationType? storageLocationType, string storageLocationId, Guid? stockOrderClassId, Guid? stockOrderId, Guid? facilityId, int pageIndex, int pageSize)
        {
            return this._stockManageContract.GetBoundRecordsByPage(materialId, materialLotId, directionType, storageLocationType, storageLocationId, stockOrderClassId, stockOrderId, facilityId, pageIndex, pageSize);
        }
        #endregion
    }
}
